#!/bin/bash
: <<COMMENT
  Copyright (C) 2012 Tri Le <trile7 at gmail dot com>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation version 3.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
COMMENT

blue='\e[0;34m'; green='\e[0;32m'; red='\e[0;31m'; yellow='\e[0;33m'; bold='\e[1m';none='\e[0m'
function menu {
  n=0
  choices=("$@")
  echo -e "$blue$bold$menutitle"
  for i in "${choices[@]}"; do
    echo -e "$none$((n++)))   $yellow$i"
  done
  echo -en "${none}c|q) ${yellow}Cancel"
  echo -e $green
  read -p "Enter a choice from above menu: " i
  echo -e $none
  [[ $i =~ c|q ]] && exit 1
  if test $i -lt $n 2>/dev/null; then
    choice=${choices[i]}; return $i
  else
    echo -e "$red$i is an invalid entry...please try again!"
    menu "${choices[@]}"
  fi
  }

function space2_ {
  newname=${1// /_}
  }

function _2space {
  newname=${1//_/ }
  }

function upper {
  newname=`echo $1 | tr [:lower:] [:upper:]`
  }

function lower {
  newname=`echo $1 | tr [:upper:] [:lower:]`
  }

function upperfirst {
  words=(`echo "$1"`)
  W=""
  for w in ${words[@]}; do
    x=`echo ${w:0:1}`
    X=`echo ${w:0:1} | tr [:lower:] [:upper:]`
    W=($W ${w/$x/$X})
  done
  newname=`echo ${W[@]}`
  }

function x2y {
  echo -ne $none
  if [[ -z $x ]]; then
    echo -e "Use wildcard ${green}?${none} to match any one character or ${green}*${none} to match all characters"
    echo -ne $green
    read -p "Enter x (find value, required): " x
    if [[ -z $x ]]; then
      err "x is required"
      x2y; return 1
    fi
  fi
  [[ $j ]] || read -p "Enter y (replacement value; leave blank to remove x): " y
  j=1
  newname=${1//$x/$y}
  }

function insert {
  echo -ne $none
  if [[ -z $pos ]]; then
    echo -e "Use ${green}0${none} for the beginning of name, ${green}end${none} for the end of name, or ${green}end-ext${none} for the end of name but keep extension."
    echo -ne $green
    read -p "Enter p (insert position, required): " pos
    if ! test $pos -ge 0 2>/dev/null  && [[ $pos != end* ]]; then
      err "$pos is invalid"
      pos=""; insert; return 1
    fi
  fi
  if [[ -z $x ]]; then
    echo -e "${none}Use ${green}%${none} to insert counter."
    echo -ne $green
    read -p "Enter x (character to insert, required): " x
    if [[ -z $x ]]; then
      err "x is required"
      insert; return 1
    fi
  fi
  if [[ $x = *%* && -z $counter ]]; then
    echo -e "${none}Start counter (include number of digits; i.e. 3 digits counter starting at 1, enter: 001)"
    echo -ne $green
    read -p "Enter start counter n (n >= 0, required): " counter
    if ! test $counter -ge 0 2>/dev/null; then
      err "$counter is invalid"
      counter=""; insert; return 1
    fi
    n=`expr $counter + ${#files[@]} - 1`
    counter=(`seq -w $counter 1 $n`)
  fi
  case $pos in
    end) p=${#1} ;;
    end-ext) noext=${1%.*}; p=${#noext} ;;
    *) p=$pos ;;
  esac
  if [[ $counter ]]; then
    c=${counter[$j]}
    ((j++))
    x1=${x//%/$c}
    newname=${1:0:$p}$x1${1:$p}
  else
    newname=${1:0:$p}$x${1:$p}
  fi
  }

function remove {
  echo -ne $none
  if [[ -z $p ]]; then
    echo -e "Use ${green}0${none} for the beginning of name"
    echo -ne $green
    read -p "Enter p (remove position, p >= 0, required): " p
    if ! test $p -ge 0 2>/dev/null; then
      err "$p is invalid"
      p=""; remove; return 1
    fi
  fi
  [[ $j ]] || read -p "Enter n (number of characters to remove; leave blank to remove all after p): " n
  j=1
  x=${1:$p:$n}
  newname=${1//$x/}
  }

function err {
  echo -e "$red$@$none"; echo; return 1
  }

function changename {
  if $cmd; then
    echo -e $none
    echo -e "${bold}Changes preview:"
    for i in "${files[@]}"; do
      $cmd "$i" || continue
      echo -e "$yellow$i -> $bold$newname"
    done
    echo -e $green
    read -p "Do you want to proceed with rename (Y/n)? " proceed
    echo -e $none
    if [[ $proceed = n ]]; then
      mainmenu
    else
      for i in "${files[@]}"; do
        $cmd "$i" || continue
        if [[ -d $i ]] && [[ $cmd = upper* || $cmd = lower ]]; then
          mv "$i" "$newname$$"
          mv "$newname$$" "$newname"
        else
          mv "$i" "$newname"
        fi
      done
    fi
  else
    mainmenu
  fi
  }

function mainmenu {
  if [[ -z $1 ]]; then
    menutitle="---Image Tools---"
    menu "Space_to_underscore" "Underscore to space" "ALL UPPERCASE" "all lowercase" "Capital First Word" "Convert x to y" "Insert counter n and/or character x at position p" "Remove n number of characters at position p"
    case $? in
      0) cmd=space2_ ;;
      1) cmd=_2space ;;
      2) cmd=upper ;;
      3) cmd=lower ;;
      4) cmd=upperfirst ;;
      5) cmd=x2y ;;
      6) cmd=insert ;;
      7) cmd=remove ;;
    esac
  fi
  changename
  }

function usage {
  echo -e $bold
  echo -e "Usage: ${0##*/} [options] filename1 filename2 ..... $none"
  echo "Options: menu is shown if option is not specified"
  echo "  --space2_     convert_space_to_underscore"
  echo "  --_2space     convert underscore to space"
  echo "  --upper       CONVERT ALL TO UPPERCASE"
  echo "  --lower       convert all to lowercase"
  echo "  --upperfirst  Convert First Letter Of A Word To Uppercase"
  echo "  --x2y         Convert x to y"
  echo "  --insert      Insert counter or characters at a specific position"
  echo "  --remove      Remove numbers of characters at a specific position"
  exit
  }

case $1 in
  -h|--h*) usage ;;
  --*) cmd=${1#--}; shift; files=("$@") ;;
  *) files=("$@") ;;
esac
[[ $# -eq 0 ]] && usage
mainmenu $cmd
